package image2

import (
	"bytes"
	"crypto/tls"
	"image"
	"image/color"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
	"micro-grpc-server/common"
	"net/http"
	"os"
	"strconv"
	"strings"
	"unicode"
)

func loadImage(file string) (image.Image, error) {
	var (
		img image.Image
		err error
	)
	// 这里为什么要定义函数而不是放在最后面
	var loadFunc = func(r io.Reader) (img image.Image, err error) {
		var (
			buf []byte
		)
		buf, err = ioutil.ReadAll(r)
		if err != nil {
			panic("图片读取失败" + err.Error())
		}

		var ext = common.ImageFileExt(buf)
		switch ext {
		case ".jpg":
			return jpeg.Decode(bytes.NewReader(buf))
		case ".png":
			return png.Decode(bytes.NewReader(buf))
		default:
			panic("不支持的图片类型")
		}
	}

	if strings.HasPrefix(file, "http") {
		var res *http.Response
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		}
		client := &http.Client{Transport: tr}
		res, err = client.Get(file)
		// 为什么要设置两次关闭通道
		// 如果这里返回的是重定向 则不能关闭 将会造成内存泄漏
		if res != nil {
			defer res.Body.Close()
		}
		if err != nil {
			return img, err
		}
		defer res.Body.Close()
		imgRes := res.Body
		return loadFunc(imgRes)
	} else {
		imgRes, err := os.Open(file)
		if err != nil {
			return img, err
		}
		defer imgRes.Close()
		return loadFunc(imgRes)
	}
}

func loadImageSize(img image.Image) (height, width int) {
	return img.Bounds().Dy(), img.Bounds().Dx()
}

func colorToRgb(colorStr string) (r, g, b int) {
	colorStr = strings.TrimPrefix(colorStr, "#")
	color64, err := strconv.ParseInt(colorStr, 16, 32)
	if err != nil {
		return
	}
	colorInt := int(color64)
	return colorInt >> 16, (colorInt & 0x00FF00) >> 8, colorInt & 0x0000FF
}

// 将颜色代码转换为rgba
func rgbaColor(colorStr string, opacity uint8) color.RGBA {
	var r, g, b int = colorToRgb(colorStr)
	return color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: opacity}
}

// 分割字符串 为字符串换行做预先处理
func splitText(str string, x int, y int, size float64, lineHeight int, width int, raw int) []Word {
	var words = make([]Word, raw)
	var (
		index      int
		word       string
		length     float64
		widthFloat = float64(width)
	)

	for _, v := range str {
		if unicode.Is(unicode.Han, v) {
			length += size
		} else {
			// 非中文算一半的宽度
			length += size / 2
		}

		if length > widthFloat {
			// 已经超长了
			words[index] = Word{
				Word:   word,
				Length: int(length),
				X:      x,
				Y:      y + lineHeight*index,
			}
			// 这个字算作下一个节点的第一个字
			word = string(v)
			length = size

			index += 1
		} else {
			word += string(v)
		}

		if index == raw {
			break
		}
	}

	// 如果最后一次循环剩下的word长度不为0 且仍然在数组范围内 就将这个word放入数组
	if word != "" && index != raw {
		words[index] = Word{
			Word:   word,
			Length: int(length),
			X:      x,
			Y:      y + lineHeight*index,
		}
	}

	return words
}
